﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Thinker.SignChannel.Entities;
using Thinker.SignChannel.Repositories;
using Thinker.SignChannel.Times;
using Volo.Abp.DependencyInjection;

namespace Thinker.SignChannel.Results;

public class ResultCalculatorFactory : ITransientDependency
{
    private readonly Dictionary<Direction, ResultCalculator> _calculators;
    private readonly IRecordRepository _recordRepository;
    private readonly ITimeRepository _timeRepository;

    public ResultCalculatorFactory(InResultCalculator inResultCalculator,
        OutResultCalculator outResultCalculator,
        ITimeRepository timeRepository,
        IRecordRepository recordRepository)
    {
        _timeRepository = timeRepository;
        _recordRepository = recordRepository;
        _calculators = new Dictionary<Direction, ResultCalculator>
        {
            { Direction.In, inResultCalculator },
            { Direction.Out, outResultCalculator }
        };
    }

    public ResultCalculator Get(Direction direction)
    {
        return _calculators[direction];
    }

    public ResultCalculator Get(Time time)
    {
        return _calculators[time.Direction];
    }

    public async Task<ResultCalculator> GetAsync(Guid timeId)
    {
        var time = await _timeRepository.GetAsync(timeId);
        return _calculators[time.Direction];
    }

    public async Task<(SignResult Result, Record? Record)> CalcAsync(PersonTime personTime)
    {
        if (personTime.SignResult == SignResult.Leave)
        {
            return (SignResult.Leave, null);
        }

        var records = await _recordRepository.FindListAsync(personTime.PersonId, personTime.TimeId);
        if (records.Count == 0)
        {
            return (SignResult.None, null);
        }

        var time = await _timeRepository.GetAsync(personTime.TimeId);
        var calculator = Get(time);
        var record = calculator.GetActiveRecord(records);
        return (calculator.Calc(time, record), record);
    }
}